package com.msf.tutorial.java8.chapter6;

import com.msf.tutorial.java8.Apple;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Stream
 *
 * 流是Java API的新成员，它允许你以声明性方式处理数据集合（通过查询语句来表达，而不是临时编写一个实现）。
 *
 * 就现在来说，你可以把它们看成遍历数据集的高级迭代器
 *
 * 此外，流还可以透明地并行处理
 *
 * 优点：
 * 1、声明性：更简洁，更易读，关注想要完成什么，而不是关注如何实现
 * 2、可复合：更灵活，可以把基础操作链接起来，来表达复杂的数据处理流水线
 * 3、可并行：性能更好
 */
public class StreamExample {

    /**
     * 第一步：从所有苹果中筛选出小苹果
     * 第二步：对所有小苹果按重量进行排序
     * 第三步：输出所有小苹果的ID
     */

    /**
     * 1.8以前的方式
     */
    private List<Long> findSmallAppleIdsBefore18(List<Apple> list) {
        List<Apple> smallApples = new ArrayList<>();
        for (Apple apple: list) {
            if (apple.getWeight() < 3) {
                smallApples.add(apple);
            }
        }

        Collections.sort(smallApples, new Comparator<Apple>() {
            public int compare(Apple d1, Apple d2){
                return Double.compare(d1.getWeight(), d2.getWeight());
            }
        });

        List<Long> idList = new ArrayList<>();
        for(Apple apple: smallApples){
            idList.add(apple.getId());
        }

        return idList;
    }

    /**
     * 使用stream
     */
    private List<Long> findSmallAppleIds18(List<Apple> list) {
        return list.stream()
                .filter((apple) -> apple.getWeight() < 3)
                .sorted(Comparator.comparing(Apple::getWeight))
                .map(Apple::getId)
                .collect(Collectors.toList());
    }

    /**
     * 利用多核架构并行执行这段代码
     *
     * 只需要把stream()换成parallelStream()
     */
    private List<Long> findSmallAppleIds18Parallel(List<Apple> list) {
        return list.parallelStream()
                .filter((apple) -> apple.getWeight() < 3)
                .sorted(Comparator.comparing(Apple::getWeight))
                .map(Apple::getId)
                .collect(Collectors.toList());
    }

}
